package com.motong.gongdan.service;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.motong.gongdan.entity.AssemblyWorkOrder;
import com.motong.gongdan.entity.AssemblyWorkOrderDetail;
import com.motong.gongdan.entity.Mission;
import com.motong.gongdan.entity.WorkOrder;
import com.motong.gongdan.enums.ObjectType;
import com.motong.gongdan.mapper.AssemblyWorkOrderMapper;
import com.motong.gongdan.util.ColumnUtils;
import com.motong.gongdan.util.LoginUtil;
import com.motong.gongdan.util.MongoUtils;
import com.motong.gongdan.vo.system.AssemblyWorkOrder.query.AssemblyListQuery;
import com.motong.gongdan.vo.system.AssemblyWorkOrder.vo.AssemblyListVo;
import com.motong.gongdan.vo.system.otherVo.CustomFieldVo;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

@Service
public class AssemblyWorkOrderService extends ServiceImpl<AssemblyWorkOrderMapper, AssemblyWorkOrder> {

    @Resource
    private AssemblyWorkOrderMapper assemblyWorkOrderMapper;

    @Resource
    private AssemblyWorkOrderDetailService assemblyWorkOrderDetailService;

    @Resource
    private CustomFieldService customFieldService;

    @Resource
    private WorkOrderService workOrderService;

    @Resource
    private MissionService missionService;

    @Resource
    private ProductService productService;

    @Resource
    private CustomEventService customEventService;

    @Resource
    MongoTemplate mongoTemplate;

    /**
     * @param page  分页条件
     * @param query 查询条件
     * @return 装配工单列表数据
     */
    public Page<AssemblyListVo> getList(Page<AssemblyWorkOrder> page, AssemblyListQuery.QueryData query) {
        Page<AssemblyListVo> data = assemblyWorkOrderMapper.getList(page, query);
        if (!CollectionUtils.isEmpty(data.getRecords())) {
            ColumnUtils columnUtils = new ColumnUtils(customFieldService, ObjectType.assembly.getCode());
            data.getRecords().forEach(i -> {
                BigDecimal endWorkerOrderNumB = BigDecimal.valueOf(i.getEndWorkerOrderNum());
                BigDecimal workerOrderNumB = BigDecimal.valueOf(i.getWorkOrderNum());
                i.setProduceProgress(i.getPlanedNum().compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : i.getFinishNum().divide(i.getPlanedNum(), 2, RoundingMode.HALF_UP));
                i.setWorkerOrderProgress(workerOrderNumB.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : endWorkerOrderNumB.divide(workerOrderNumB, 2, RoundingMode.HALF_UP));
                List<CustomFieldVo> cuColumnsByJsonArray = columnUtils.getCuColumnsByJsonArray(i.getOther());
                i.setVos(cuColumnsByJsonArray);
            });
        }
        return data;
    }

    /**
     * 删除装配工单详情相关信息
     *
     * @param delDetailIds 需要删除的ids x
     */
    public void delDetail(List<Long> delDetailIds) {
        List<AssemblyWorkOrderDetail> formTableDetails = assemblyWorkOrderDetailService.listByIds(delDetailIds);
        // 工单编码
        Set<String> wOCodes = formTableDetails.stream().map(AssemblyWorkOrderDetail::getWorkerOrderCode).collect(Collectors.toSet());
        workOrderService.removeByCodeList(wOCodes);
        // 删除详情
        assemblyWorkOrderDetailService.removeByIds(delDetailIds);
    }

    /**
     * 添加装配工单详情
     *
     * @param saveList         装配工单内部详情信息
     * @param id               装配工单id
     * @param code             销售订单编码
     * @param workerOrderIndex 当前详情数量+1(即生成工单的下标)
     */
    public void saveDetail(List<AssemblyWorkOrderDetail> saveList, Long id, String code, int workerOrderIndex) {
        if (CollectionUtils.isEmpty(saveList)) {
            return;
        }
        // 根据产品id获取绑定的工艺路线
        Set<Integer> productIds = saveList.stream().map(AssemblyWorkOrderDetail::getProductId).collect(Collectors.toSet());
        // 需要用到的商品信息
        List<Map<String, Object>> productData = productService.getProcessByProductId(productIds);
        Integer loginUserId = LoginUtil.getLoginUserId();
        Map<Integer, Map<String, Object>> productIdDataMap = new HashMap<>();
        productData.forEach(i -> productIdDataMap.put(Integer.valueOf(i.get("productId").toString()), i));
        List<WorkOrder> workOrders = new ArrayList<>();
        List<Mission> missions = new ArrayList<>();
        List<AssemblyWorkOrderDetail> assemblyWorkOrderDetails = new ArrayList<>();
        AtomicReference<Integer> num = new AtomicReference<>(workerOrderIndex);
        saveList.forEach(i -> {
            DateTime date = DateUtil.date();
            Date planStartTime = Optional.ofNullable(i.getPlanStartTime()).orElse(DateUtil.beginOfDay(date));
            Date planEndTime = Optional.ofNullable(i.getPlanEndTime()).orElse(DateUtil.endOfDay(date));
            Map<String, Object> product = productIdDataMap.get(i.getProductId());
            cn.hutool.json.JSONArray processList = JSONUtil.parseArray(Optional.ofNullable(product.get("processList")).orElse("[]"));
            String processIds = processList.stream().map(d -> JSONUtil.parseObj(d).get("id").toString()).collect(Collectors.joining(","));
            // 整合工单数据
            WorkOrder workOrder = new WorkOrder().setStartTime(planStartTime).setEndTime(planEndTime).setOther(JSONUtil.toJsonStr(i.getCustomFieldVos()))
                    .setPlanedNumber(i.getWorkOrderPlanNum()).setActualNumber(BigDecimal.ZERO).setState(0)
                    .setProductId(Convert.toInt(product.get("productId"))).setCreateId(loginUserId).setEditId(loginUserId).setProcessId(processIds).setIsUrgent(0);
            workOrder.setCode(code + "-" + num);
            num.getAndSet(num.get() + 1);
            AssemblyWorkOrderDetail assemblyWorkOrderDetail = new AssemblyWorkOrderDetail().setParentLevel(i.getParentLevel())
                    .setCreateUser(loginUserId).setCreateTime(new Date()).setWorkerOrderCode(workOrder.getCode()).setLevel(i.getLevel())
                    .setAssemblyWorkOrderId(id).setWorkOrderPlanNum(i.getWorkOrderPlanNum()).setRemark(i.getRemark()).setUnitUsage(i.getUnitUsage())
                    .setProductId(i.getProductId()).setUpdateTime(new Date()).setUpdateUser(loginUserId);
            assemblyWorkOrderDetails.add(assemblyWorkOrderDetail);
            // 整合任务数据
            // 最后一道工序order为0!!!!!
            AtomicInteger order = new AtomicInteger(1);
            processList.forEach(
                    d -> {
                        cn.hutool.json.JSONObject process = JSONUtil.parseObj(d);
                        Mission mission = new Mission().setWorkOrderCode(workOrder.getCode()).setProcessCode(process.get("code").toString())
                                .setPlanedNumber(Convert.toBigDecimal(process.get("rate")).multiply(i.getWorkOrderPlanNum()))
                                .setRate(Convert.toBigDecimal(process.get("rate"))).setLast(order.get() == processList.size() ? 0 : order.getAndIncrement())
                                .setStartTime(workOrder.getStartTime()).setEndTime(workOrder.getEndTime()).setProcessState(0).setProductCode(product.get("productCode").toString()).setIsUrgent(0);
                        missions.add(mission);
                    }
            );
            workOrders.add(workOrder);
            customEventService.sendCustomEventMsg(0, 0, 0, workOrder, null, null);
        });
        workOrderService.saveBatch(workOrders);
        workOrders.stream().filter(i -> StringUtils.hasLength(i.getOther())).forEach(i -> workOrderService.cacheCustomToMongo(i));
        missionService.saveBatch(missions);
        Map<String, Integer> workOrderCodeIdMap = new HashMap<>(workOrders.size());
        workOrders.forEach(i -> workOrderCodeIdMap.put(i.getCode(), i.getId()));
        assemblyWorkOrderDetails.forEach(i -> i.setWorkerOrderId(workOrderCodeIdMap.get(i.getWorkerOrderCode())));
        assemblyWorkOrderDetailService.saveBatch(assemblyWorkOrderDetails);
    }

    public void updateDetail(List<AssemblyWorkOrderDetail> updateVo) {
        if (CollectionUtils.isEmpty(updateVo)) {
            return;
        }
        // 获取工单编码
        Set<String> wOCodes = updateVo.stream().map(AssemblyWorkOrderDetail::getWorkerOrderCode).collect(Collectors.toSet());
        // 获取所有工单信息
        Map<String, WorkOrder> codeOrderData = new HashMap<>();
        workOrderService.list(new LambdaQueryWrapper<WorkOrder>().in(WorkOrder::getCode, wOCodes)).forEach(i -> codeOrderData.put(i.getCode(), i));
        // 筛选需要操作的工单,任务
        List<WorkOrder> workOrders = new ArrayList<>();
        List<Mission> missions;
        Map<String, WorkOrder> codeDataMap = new HashMap<>();
        List<AssemblyWorkOrderDetail> assemblyWorkOrderDetails = new ArrayList<>();
        if (codeOrderData.isEmpty()) {
            return;
        }
        updateVo.forEach(i -> {
                    WorkOrder workOrder = codeOrderData.get(i.getWorkerOrderCode());
                    String workOrderOther = JSONUtil.toJsonStr(i.getCustomFieldVos());
                    if (Objects.nonNull(workOrder) && (!workOrder.getPlanedNumber().equals(i.getWorkOrderPlanNum()) ||
                            !workOrder.getStartTime().equals(i.getPlanStartTime()) || !workOrder.getEndTime().equals(i.getPlanEndTime())
                            || !workOrder.getOther().equals(workOrderOther))) {
                        codeDataMap.put(workOrder.getCode(), workOrder);
                        if (!workOrder.getPlanedNumber().equals(i.getWorkOrderPlanNum())) {
                            workOrder.setPlanedNumber(i.getWorkOrderPlanNum());
                        }
                        if (!workOrder.getStartTime().equals(i.getPlanStartTime())) {
                            workOrder.setStartTime(i.getPlanStartTime());
                        }
                        if (!workOrder.getEndTime().equals(i.getPlanEndTime())) {
                            workOrder.setEndTime(i.getPlanEndTime());
                        }
                        if (!workOrder.getOther().equals(workOrderOther)) {
                            workOrder.setOther(workOrderOther);
                            MongoUtils.deleteById(workOrder.getId(), mongoTemplate, ObjectType.workOrder.getCode());
                            workOrderService.cacheCustomToMongo(workOrder);
                        }
                        assemblyWorkOrderDetails.add(new AssemblyWorkOrderDetail().setId(i.getId()).setLevel(i.getLevel())
                                .setParentLevel(i.getParentLevel())
                                .setWorkOrderPlanNum(i.getWorkOrderPlanNum()).setProductId(i.getProductId()));
                        workOrders.add(workOrder);
                    }
                }
        );
        // 获取需要更新的任务信息
        missions = missionService.list(new LambdaQueryWrapper<Mission>().in(Mission::getWorkOrderCode, workOrders.stream().map(WorkOrder::getCode).collect(Collectors.toSet())));
        missions.forEach(i -> {
            WorkOrder workOrder = codeDataMap.get(i.getWorkOrderCode());
            i.setPlanedNumber(i.getRate().multiply(workOrder.getPlanedNumber()))
                    .setStartTime(workOrder.getStartTime()).setEndTime(i.getEndTime());
        });

        if (!workOrders.isEmpty()) {
            workOrderService.updateBatchById(workOrders);
            assemblyWorkOrderDetailService.updateBatchById(assemblyWorkOrderDetails);
        }
        if (!missions.isEmpty()) {
            missionService.updateBatchById(missions);
        }
    }


    /**
     * 获取单条导入数据
     */
    public Map<String, Object> getExportData(String assemblyId) {
        return this.assemblyWorkOrderMapper.getExportData(assemblyId);
    }

    /**
     * 获取导入数据详情
     */
    public List<Map<String, Object>> getExportDataList(String assemblyId) {
        List<Map<String, Object>> exportDataList = this.assemblyWorkOrderMapper.getExportDataList(assemblyId);
        if (!CollectionUtils.isEmpty(exportDataList)) {
            ColumnUtils columnUtils = new ColumnUtils(customFieldService, ObjectType.workOrder.getCode());
            exportDataList.forEach(i -> {
                if (Objects.nonNull(i.get("productDetailOther"))) {
                    List<CustomFieldVo> productDetailOther = columnUtils.getCuColumnsByJsonArray(i.get("productDetailOther").toString());
                    productDetailOther.forEach(d -> i.put(d.getName(), d.getValue()));
                }
                if (Objects.nonNull(i.get("productDetailQr"))) {
                    String qrPath = i.get("productDetailQr").toString();
                    String replace = "https://mtgongdan.com".concat(qrPath.replace("/service", ""));
                    try {
                        i.put("productDetailQr", new URL(replace));
                    } catch (MalformedURLException e) {
                        e.printStackTrace();
                    }

                }
            });
        }
        return this.assemblyWorkOrderMapper.getExportDataList(assemblyId);
    }
}
